home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 7 / Amiga Format AFCD07 (Dec 1996, Issue 91).iso / serious / shareware / programming / aros / filesys / emul_handler.c < prev    next >
C/C++ Source or Header  |  1996-09-13  |  17KB  |  714 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: emul_handler.c,v 1.10 1996/09/13 17:57:07 digulla Exp $
  4.     $Log: emul_handler.c,v $
  5.     Revision 1.10  1996/09/13 17:57:07  digulla
  6.     Use IPTR
  7.  
  8.     Revision 1.9  1996/09/13 04:23:23  aros
  9.     Define FreeBSD should have been __FreeBSD__ (sorry my fault).
  10.  
  11.     Revision 1.8  1996/09/11 16:54:24  digulla
  12.     Always use __AROS_SLIB_ENTRY() to access shared external symbols, because
  13.     some systems name an external symbol "x" as "_x" and others as "x".
  14.     (The problem arises with assembler symbols which might differ)
  15.  
  16.     Revision 1.7  1996/09/11 14:40:10  digulla
  17.     Integrated patch by I. Templeton: Under FreeBSD, there is a clash with
  18.     struct timeval
  19.  
  20.     Revision 1.6  1996/09/11 13:05:34  digulla
  21.     Own function to open a file (M. Fleischer)
  22.  
  23.     Revision 1.5  1996/08/31 12:58:11  aros
  24.     Merged in/modified for FreeBSD.
  25.  
  26.     Revision 1.4  1996/08/30 17:02:06  digulla
  27.     Fixed a bug which caused the shell to exit if the timer sent a signal. This
  28.     fix is a very bad hack :(
  29.  
  30.     Revision 1.3  1996/08/13 15:35:07  digulla
  31.     Replaced __AROS_LA by __AROS_LHA
  32.  
  33.     Revision 1.2  1996/08/01 17:41:22  digulla
  34.     Added standard header for all files
  35.  
  36.     Desc:
  37.     Lang:
  38. */
  39. #include <exec/resident.h>
  40. #include <exec/memory.h>
  41. #include <clib/exec_protos.h>
  42. #include <utility/tagitem.h>
  43. #include <dos/dosextens.h>
  44. #include <dos/filesystem.h>
  45. #include <dos/exall.h>
  46. #include <dos/dosasl.h>
  47. #include <clib/dos_protos.h>
  48. #include <aros/libcall.h>
  49. #include <unistd.h>
  50. #include <fcntl.h>
  51. #include <dirent.h>
  52. #include <string.h>
  53. #include <stdlib.h>
  54. #include <errno.h>
  55. #if defined(__FreeBSD__)
  56. #define timeval _timeval
  57. #include <sys/stat.h>
  58. #define tv_sec tv_secs
  59. #define tv_usec tv_micros
  60. #undef timeval
  61. #else
  62. #include <sys/stat.h>
  63. #endif
  64. #ifdef __GNUC__
  65.     #include "emul_handler_gcc.h"
  66. #endif
  67.  
  68. static const char name[];
  69. static const char version[];
  70. static const APTR inittabl[4];
  71. static void *const functable[];
  72. static const UBYTE datatable;
  73.  
  74. struct emulbase * __AROS_SLIB_ENTRY(init,emul_handler) ();
  75. void __AROS_SLIB_ENTRY(open,emul_handler) ();
  76. BPTR __AROS_SLIB_ENTRY(close,emul_handler) ();
  77. BPTR __AROS_SLIB_ENTRY(expunge,emul_handler) ();
  78. int __AROS_SLIB_ENTRY(null,emul_handler) ();
  79. void __AROS_SLIB_ENTRY(beginio,emul_handler) ();
  80. LONG __AROS_SLIB_ENTRY(abortio,emul_handler) ();
  81.  
  82. static const char end;
  83.  
  84. struct filehandle
  85. {
  86.     char *name;
  87.     int type;
  88.     long fd;
  89. };
  90. #define FHD_FILE    0
  91. #define FHD_DIRECTORY    1
  92.  
  93. int emul_handler_entry(void)
  94. {
  95.     /* If the device was executed by accident return error code. */
  96.     return -1;
  97. }
  98.  
  99. const struct Resident emul_handler_resident=
  100. {
  101.     RTC_MATCHWORD,
  102.     (struct Resident *)&emul_handler_resident,
  103.     (APTR)&end,
  104.     RTF_AUTOINIT,
  105.     1,
  106.     NT_LIBRARY,
  107.     0,
  108.     (char *)name,
  109.     (char *)&version[6],
  110.     (ULONG *)inittabl
  111. };
  112.  
  113. static const char name[]="emul.handler";
  114.  
  115. static const char version[]="$VER: emul_handler 1.0 (28.3.96)\n\015";
  116.  
  117. static const APTR inittabl[4]=
  118. {
  119.     (APTR)sizeof(struct emulbase),
  120.     (APTR)functable,
  121.     (APTR)&datatable,
  122.     &__AROS_SLIB_ENTRY(init,emul_handler)
  123. };
  124.  
  125. static void *const functable[]=
  126. {
  127.     &__AROS_SLIB_ENTRY(open,emul_handler),
  128.     &__AROS_SLIB_ENTRY(close,emul_handler),
  129.     &__AROS_SLIB_ENTRY(expunge,emul_handler),
  130.     &__AROS_SLIB_ENTRY(null,emul_handler),
  131.     &__AROS_SLIB_ENTRY(beginio,emul_handler),
  132.     &__AROS_SLIB_ENTRY(abortio,emul_handler),
  133.     (void *)-1
  134. };
  135.  
  136. static const UBYTE datatable=0;
  137.  
  138. LONG u2a[][2]=
  139. {
  140.   { ENOMEM, ERROR_NO_FREE_STORE },
  141.   { ENOENT, ERROR_OBJECT_NOT_FOUND },
  142.   { EINTR,  -1 }, /*ada 30.8.96 This is a REALLY BAD hack !! */
  143.   { 0, 0 }
  144. };
  145.  
  146. LONG err_u2a(void)
  147. {
  148.     ULONG i;
  149.     for(i=0;i<sizeof(u2a)/sizeof(u2a[0]);i++)
  150.     if(u2a[i][0]==errno)
  151.         break;
  152.     return u2a[i][1];
  153. }
  154.  
  155. static void shrink(char *filename)
  156. {
  157.     char *s1,*s2;
  158.     unsigned long len;
  159.     for(;;)
  160.     {
  161.     while(*filename=='/')
  162.         memmove(filename,filename+1,strlen(filename));
  163.     s1=strstr(filename,"//");
  164.     if(s1==NULL)
  165.         break;
  166.     s2=s1;
  167.     while(s2>filename&&*--s2!='/')
  168.         ;
  169.     memmove(s2,s1+2,strlen(s1+1));
  170.     }
  171.     len=strlen(filename);
  172.     if(len&&filename[len-1]=='/')
  173.     filename[len-1]=0;
  174. }
  175.  
  176. static LONG open_(struct filehandle **handle,STRPTR name,LONG mode)
  177. {
  178.     LONG ret=ERROR_NO_FREE_STORE;
  179.     struct filehandle *fh;
  180.     struct stat st;
  181.     long flags;
  182.     fh=(struct filehandle *)malloc(sizeof(struct filehandle));
  183.     if(fh!=NULL)
  184.     {
  185.     if(!*name&&(*handle)->type==FHD_FILE&&((*handle)->fd==STDIN_FILENO||
  186.        (*handle)->fd==STDOUT_FILENO||(*handle)->fd==STDERR_FILENO))
  187.     {
  188.         fh->type=FHD_FILE;
  189.         fh->fd=(*handle)->fd;
  190.         fh->name="";
  191.         *handle=fh;
  192.         return 0;
  193.     }
  194.     fh->name=(char *)malloc(strlen((*handle)->name)+strlen(name)+2);
  195.     if(fh->name!=NULL)
  196.     {
  197.         strcpy(fh->name,(*handle)->name);
  198.         strcat(fh->name,"/");
  199.         strcat(fh->name,name);
  200.         shrink(fh->name);
  201.         if(!stat(*fh->name?fh->name:".",&st))
  202.         {
  203.         if(S_ISREG(st.st_mode))
  204.         {
  205.             fh->type=FHD_FILE;
  206.             flags=(mode&FMF_CREATE?O_CREAT:0)|
  207.               (mode&FMF_CLEAR?O_TRUNC:0);
  208.             if(mode&FMF_WRITE)
  209.             flags|=mode&FMF_READ?O_RDWR:O_WRONLY;
  210.             else
  211.             flags|=O_RDONLY;
  212.             fh->fd=open(*fh->name?fh->name:".",flags,0770);
  213.             if(fh->fd>=0)
  214.             {
  215.             *handle=fh;
  216.             return 0;
  217.             }
  218.         }else if(S_ISDIR(st.st_mode))
  219.         {
  220.             fh->type=FHD_DIRECTORY;
  221.             fh->fd=(long)opendir(*fh->name?fh->name:".");
  222.             if(fh->fd)
  223.             {
  224.             *handle=fh;
  225.             return 0;
  226.             }
  227.         }else
  228.             errno=ENOENT;
  229.         }
  230.         ret=err_u2a();
  231.         free(fh->name);
  232.     }
  233.     free(fh);
  234.     }
  235.     return ret;
  236. }
  237.  
  238. static LONG open_file(struct filehandle **handle,STRPTR name,LONG mode,LONG protect)
  239. {
  240.     LONG ret=ERROR_NO_FREE_STORE;
  241.     struct filehandle *fh;
  242.     long flags;
  243.     fh=(struct filehandle *)malloc(sizeof(struct filehandle));
  244.     if(fh!=NULL)
  245.     {
  246.     if(!*name&&(*handle)->type==FHD_FILE&&((*handle)->fd==STDIN_FILENO||
  247.        (*handle)->fd==STDOUT_FILENO||(*handle)->fd==STDERR_FILENO))
  248.     {
  249.         fh->type=FHD_FILE;
  250.         fh->fd=(*handle)->fd;
  251.         fh->name="";
  252.         *handle=fh;
  253.         return 0;
  254.     }
  255.     fh->name=(char *)malloc(strlen((*handle)->name)+strlen(name)+2);
  256.     if(fh->name!=NULL)
  257.     {
  258.         strcpy(fh->name,(*handle)->name);
  259.         strcat(fh->name,"/");
  260.         strcat(fh->name,name);
  261.         shrink(fh->name);
  262.         fh->type=FHD_FILE;
  263.         flags=(mode&FMF_CREATE?O_CREAT:0)|
  264.           (mode&FMF_CLEAR?O_TRUNC:0);
  265.         if(mode&FMF_WRITE)
  266.         flags|=mode&FMF_READ?O_RDWR:O_WRONLY;
  267.         else
  268.         flags|=O_RDONLY;
  269.         fh->fd=open(fh->name,flags,0770);
  270.         if(fh->fd>=0)
  271.         {
  272.         *handle=fh;
  273.         return 0;
  274.         }
  275.         ret=err_u2a();
  276.         free(fh->name);
  277.     }
  278.     free(fh);
  279.     }
  280.     return ret;
  281. }
  282.  
  283. static LONG free_lock(struct filehandle *current)
  284. {
  285.     switch(current->type)
  286.     {
  287.     case FHD_FILE:
  288.         if(current->fd!=STDIN_FILENO&¤t->fd!=STDOUT_FILENO&&
  289.            current->fd!=STDERR_FILENO)
  290.         {
  291.         close(current->fd);
  292.         free(current->name);
  293.         }
  294.         break;
  295.     case FHD_DIRECTORY:
  296.         closedir((DIR *)current->fd);
  297.         free(current->name);
  298.         break;
  299.     }
  300.     free(current);
  301.     return 0;
  302. }
  303.  
  304. static LONG startup(struct emulbase *emulbase)
  305. {
  306.     struct filehandle *fhi, *fho, *fhe, *fhv, *fhc, *fhs;
  307.     struct DosList *dlv, *dlc;
  308.     static struct filehandle sys={ "", FHD_DIRECTORY, 0 };
  309.     LONG ret=ERROR_NO_FREE_STORE;
  310.  
  311.     fhi=(struct filehandle *)malloc(sizeof(struct filehandle));
  312.     if(fhi!=NULL)
  313.     {
  314.     fho=(struct filehandle *)malloc(sizeof(struct filehandle));
  315.     if(fho!=NULL)
  316.     {
  317.         fhe=(struct filehandle *)malloc(sizeof(struct filehandle));
  318.         if(fhe!=NULL)
  319.         {
  320.         fhv=&sys;
  321.         ret=open_(&fhv,"",0);
  322.         if(!ret)
  323.         {
  324.             fhc=&sys;
  325.             ret=open_(&fhc,"",0);
  326.             if(!ret)
  327.             {
  328.             fhs=&sys;
  329.             ret=open_(&fhs,"",0);
  330.             if(!ret)
  331.             {
  332.                 ret=ERROR_NO_FREE_STORE;
  333.                 dlv=MakeDosEntry("Workbench",DLT_VOLUME);
  334.                 if(dlv!=NULL)
  335.                 {
  336.                 dlc=MakeDosEntry("SYS",DLT_DEVICE);
  337.                 if(dlc!=NULL)
  338.                 {
  339.                     ret=ERROR_OBJECT_EXISTS;
  340.                     dlv->dol_Unit  =(struct Unit *)fhv;
  341.                     dlv->dol_Device=&emulbase->device;
  342.                     dlc->dol_Unit  =(struct Unit *)fhc;
  343.                     dlc->dol_Device=&emulbase->device;
  344.                     fhi->type=FHD_FILE;
  345.                     fhi->fd=STDIN_FILENO;
  346.                     fhi->name="";
  347.                     emulbase->stdin=(struct Unit *)fhi;
  348.                     fho->type=FHD_FILE;
  349.                     fho->fd=STDOUT_FILENO;
  350.                     fho->name="";
  351.                     emulbase->stdout=(struct Unit *)fho;
  352.                     fhe->type=FHD_FILE;
  353.                     fhe->fd=STDERR_FILENO;
  354.                     fhe->name="";
  355.                     emulbase->stderr=(struct Unit *)fhe;
  356.                     if(AddDosEntry(dlv))
  357.                     {
  358.                     if(AddDosEntry(dlc))
  359.                     {
  360.                         DOSBase->dl_NulHandler=&emulbase->device;
  361.                         DOSBase->dl_NulLock   =(struct Unit *)fhs;
  362.                         return 0;
  363.                     }
  364.                     RemDosEntry(dlv);
  365.                     }
  366.                     FreeDosEntry(dlc);
  367.                 }
  368.                 FreeDosEntry(dlv);
  369.                 }
  370.                 free_lock(fhs);
  371.             }
  372.             free_lock(fhc);
  373.             }
  374.             free_lock(fhv);
  375.         }
  376.         free(fhe);
  377.         }
  378.         free(fho);
  379.     }
  380.     free(fhi);
  381.     }
  382.     return ret;
  383. }
  384.  
  385. static const ULONG sizes[]=
  386. { 0, offsetof(struct ExAllData,ed_Type), offsetof(struct ExAllData,ed_Size),
  387.   offsetof(struct ExAllData,ed_Prot), offsetof(struct ExAllData,ed_Days),
  388.   offsetof(struct ExAllData,ed_Comment), offsetof(struct ExAllData,ed_OwnerUID),
  389.   sizeof(struct ExAllData) };
  390.  
  391. static LONG examine(struct filehandle *fh,struct ExAllData *ead,ULONG size,ULONG type)
  392. {
  393.     STRPTR next, end, last, name;
  394.     struct stat st;
  395.     if(type>ED_OWNER)
  396.     return ERROR_BAD_NUMBER;
  397.     next=(STRPTR)ead+sizes[type];
  398.     end =(STRPTR)ead+size;
  399.     if(next>=end)
  400.     return ERROR_BUFFER_OVERFLOW;
  401.     if(lstat(*fh->name?fh->name:".",&st))
  402.     return err_u2a();
  403.     switch(type)
  404.     {
  405.     default:
  406.     case ED_OWNER:
  407.         ead->ed_OwnerUID=st.st_uid;
  408.         ead->ed_OwnerGID=st.st_gid;
  409.     case ED_COMMENT:
  410.         ead->ed_Comment=NULL;
  411.     case ED_DATE:
  412.         ead->ed_Days=st.st_ctime/(60*60*24)-(6*365+2*366);
  413.         ead->ed_Mins=(st.st_ctime/60)%(60*24);
  414.         ead->ed_Ticks=(st.st_ctime%60)*TICKS_PER_SECOND;
  415.     case ED_PROTECTION:
  416.         ead->ed_Prot=(st.st_mode&S_IRUSR?FIBF_READ:0)|
  417.              (st.st_mode&S_IWUSR?FIBF_WRITE:0)|
  418.              (st.st_mode&S_IXUSR?FIBF_EXECUTE:0)|
  419.              FIBF_SCRIPT|FIBF_DELETE;
  420.     case ED_SIZE:
  421.         ead->ed_Size=st.st_size;
  422.     case ED_TYPE:
  423.         ead->ed_Type=S_ISREG(st.st_mode)?ST_FILE:
  424.              S_ISDIR(st.st_mode)?(*fh->name?ST_USERDIR:ST_ROOT):0;
  425.     case ED_NAME:
  426.         ead->ed_Name=next;
  427.         last=name=*fh->name?fh->name:"Workbench";
  428.         while(*name)
  429.         if(*name++=='/')
  430.             last=name;
  431.         for(;;)
  432.         {
  433.         if(next>=end)
  434.             return ERROR_BUFFER_OVERFLOW;
  435.         if(!(*next++=*last++))
  436.             break;
  437.         }
  438.     case 0:
  439.         ead->ed_Next=(struct ExAllData *)(((IPTR)next+PTRALIGN-1)&~(PTRALIGN-1));
  440.         return 0;
  441.     }
  442. }
  443.  
  444. static LONG examine_all(struct filehandle *fh,struct ExAllData *ead,ULONG size,ULONG type)
  445. {
  446.     struct ExAllData *last=NULL;
  447.     STRPTR end=(STRPTR)ead+size, name, old;
  448.     off_t oldpos;
  449.     struct dirent *dir;
  450.     LONG error;
  451.     if(fh->type!=FHD_DIRECTORY)
  452.     return ERROR_OBJECT_WRONG_TYPE;
  453.     for(;;)
  454.     {
  455.     oldpos=telldir((DIR *)fh->fd);
  456.     errno=0;
  457.     dir=readdir((DIR *)fh->fd);
  458.     if(dir==NULL)
  459.     {
  460.         error=err_u2a();
  461.         break;
  462.     }
  463.     if(dir->d_name[0]=='.'&&(!dir->d_name[1]||(dir->d_name[1]=='.'&&!dir->d_name[2])))
  464.         continue;
  465.     name=(STRPTR)malloc(strlen(fh->name)+strlen(dir->d_name)+2);
  466.     if(name==NULL)
  467.     {
  468.         error=ERROR_NO_FREE_STORE;
  469.         break;
  470.     }
  471.     strcpy(name,fh->name);
  472.     if(*name)
  473.         strcat(name,"/");
  474.     strcat(name,dir->d_name);
  475.     old=fh->name;
  476.     fh->name=name;
  477.     error=examine(fh,ead,end-(STRPTR)ead,type);
  478.     fh->name=old;
  479.     free(name);
  480.     if(error)
  481.         break;
  482.     last=ead;
  483.     ead=ead->ed_Next;
  484.     }
  485.     if((!error||error==ERROR_BUFFER_OVERFLOW)&&last!=NULL)
  486.     {
  487.     last->ed_Next=NULL;
  488.     seekdir((DIR *)fh->fd,oldpos);
  489.     return 0;
  490.     }
  491.     if(!error)
  492.     error=ERROR_NO_MORE_ENTRIES;
  493.     rewinddir((DIR *)fh->fd);
  494.     return error;
  495. }
  496.  
  497. __AROS_LH2(struct emulbase *, init,
  498.  __AROS_LHA(struct emulbase *, emulbase, D0),
  499.  __AROS_LHA(BPTR,              segList,   A0),
  500.        struct ExecBase *, sysBase, 0, emul_handler)
  501. {
  502.     __AROS_FUNC_INIT
  503.  
  504.     /* Store arguments */
  505.     emulbase->sysbase=sysBase;
  506.     emulbase->seglist=segList;
  507.     emulbase->device.dd_Library.lib_OpenCnt=1;
  508.     emulbase->dosbase=(struct DosLibrary *)OpenLibrary("dos.library",39);
  509.     if(emulbase->dosbase!=NULL)
  510.     {
  511.     if(AttemptLockDosList(LDF_ALL|LDF_WRITE))
  512.     {
  513.         if(!startup(emulbase))
  514.         {
  515.         UnLockDosList(LDF_ALL|LDF_WRITE);
  516.         return emulbase;
  517.         }
  518.         UnLockDosList(LDF_ALL|LDF_WRITE);
  519.     }
  520.     CloseLibrary((struct Library *)emulbase->dosbase);
  521.     }
  522.  
  523.     return NULL;
  524.     __AROS_FUNC_EXIT
  525. }
  526.  
  527. __AROS_LH3(void, open,
  528.  __AROS_LHA(struct IOFileSys *, iofs, A1),
  529.  __AROS_LHA(ULONG,              unitnum, D0),
  530.  __AROS_LHA(ULONG,              flags, D0),
  531.        struct emulbase *, emulbase, 1, emul_handler)
  532. {
  533.     __AROS_FUNC_INIT
  534.  
  535.     /* Keep compiler happy */
  536.     unitnum=0;
  537.     flags=0;
  538.  
  539.     /* I have one more opener. */
  540.     emulbase->device.dd_Library.lib_Flags&=~LIBF_DELEXP;
  541.  
  542.     /* Set returncode */
  543.     iofs->IOFS.io_Error=0;
  544.  
  545.     /* Mark Message as recently used. */
  546.     iofs->IOFS.io_Message.mn_Node.ln_Type=NT_REPLYMSG;
  547.     __AROS_FUNC_EXIT
  548. }
  549.  
  550. __AROS_LH1(BPTR, close,
  551.  __AROS_LHA(struct IOFileSys *, iofs, A1),
  552.        struct emulbase *, emulbase, 2, emul_handler)
  553. {
  554.     __AROS_FUNC_INIT
  555.  
  556.     /* Let any following attemps to use the device crash hard. */
  557.     iofs->IOFS.io_Device=(struct Device *)-1;
  558.     return 0;
  559.     __AROS_FUNC_EXIT
  560. }
  561.  
  562. __AROS_LH0(BPTR, expunge, struct emulbase *, emulbase, 3, emul_handler)
  563. {
  564.     __AROS_FUNC_INIT
  565.  
  566.     /* Do not expunge the device. Set the delayed expunge flag and return. */
  567.     emulbase->device.dd_Library.lib_Flags|=LIBF_DELEXP;
  568.     return 0;
  569.     __AROS_FUNC_EXIT
  570. }
  571.  
  572. __AROS_LH0I(int, null, struct emulbase *, emulbase, 4, emul_handler)
  573. {
  574.     __AROS_FUNC_INIT
  575.     return 0;
  576.     __AROS_FUNC_EXIT
  577. }
  578.  
  579. __AROS_LH1(void, beginio,
  580.  __AROS_LHA(struct IOFileSys *, iofs, A1),
  581.        struct emulbase *, emulbase, 5, emul_handler)
  582. {
  583.     __AROS_FUNC_INIT
  584.     LONG error=0;
  585.  
  586.     /* WaitIO will look into this */
  587.     iofs->IOFS.io_Message.mn_Node.ln_Type=NT_MESSAGE;
  588.  
  589.     /*
  590.     Do everything quick no matter what. This is possible
  591.     because I never need to Wait().
  592.     */
  593.     switch(iofs->IOFS.io_Command)
  594.     {
  595.     case FSA_OPEN:
  596.         error=open_((struct filehandle **)&iofs->IOFS.io_Unit,
  597.              (char *)iofs->io_Args[0],iofs->io_Args[1]);
  598.         break;
  599.  
  600.     case FSA_OPEN_FILE:
  601.         error=open_file((struct filehandle **)&iofs->IOFS.io_Unit,
  602.              (char *)iofs->io_Args[0],
  603.              iofs->io_Args[1],iofs->io_Args[2]);
  604.         break;
  605.  
  606.     case FSA_CLOSE:
  607.         error=free_lock((struct filehandle *)iofs->IOFS.io_Unit);
  608.         break;
  609.  
  610.     case FSA_IS_INTERACTIVE:
  611.     {
  612.         struct filehandle *fh=(struct filehandle *)iofs->IOFS.io_Unit;
  613.         if(fh->type==FHD_FILE)
  614.         iofs->io_Args[0]=isatty(fh->fd);
  615.         else
  616.         iofs->io_Args[0]=0;
  617.         break;
  618.     }
  619.  
  620.     case FSA_READ:
  621.     {
  622.         struct filehandle *fh=(struct filehandle *)iofs->IOFS.io_Unit;
  623.         if(fh->type==FHD_FILE)
  624.         {
  625.         if(fh->fd==STDOUT_FILENO)
  626.             fh->fd=STDIN_FILENO;
  627.         iofs->io_Args[1]=read(fh->fd,(APTR)iofs->io_Args[0],iofs->io_Args[1]);
  628.         if(iofs->io_Args[1]<0)
  629.             error=err_u2a();
  630.         }else
  631.         error=ERROR_OBJECT_WRONG_TYPE;
  632.         break;
  633.     }
  634.  
  635.     case FSA_WRITE:
  636.     {
  637.         struct filehandle *fh=(struct filehandle *)iofs->IOFS.io_Unit;
  638.         if(fh->type==FHD_FILE)
  639.         {
  640.         if(fh->fd==STDIN_FILENO)
  641.             fh->fd=STDOUT_FILENO;
  642.         iofs->io_Args[1]=write(fh->fd,(APTR)iofs->io_Args[0],iofs->io_Args[1]);
  643.         if(iofs->io_Args[1]<0)
  644.             error=err_u2a();
  645.         }else
  646.         error=ERROR_OBJECT_WRONG_TYPE;
  647.         break;
  648.     }
  649.  
  650.     case FSA_SEEK:
  651.     {
  652.         struct filehandle *fh=(struct filehandle *)iofs->IOFS.io_Unit;
  653.         LONG mode=iofs->io_Args[2];
  654.         LONG oldpos;
  655.         if(fh->type==FHD_FILE)
  656.         {
  657.         oldpos=lseek(fh->fd,0,SEEK_CUR);
  658.         if(lseek(fh->fd,iofs->io_Args[1],mode==OFFSET_BEGINNING?SEEK_SET:mode==OFFSET_CURRENT?SEEK_CUR:SEEK_END)<0)
  659.             error=err_u2a();
  660.         iofs->io_Args[0]=0;
  661.         iofs->io_Args[1]=oldpos;
  662.         }else
  663.         error=ERROR_OBJECT_WRONG_TYPE;
  664.         break;
  665.     }
  666.  
  667.     case FSA_EXAMINE:
  668.         error=examine((struct filehandle *)iofs->IOFS.io_Unit,
  669.               (struct ExAllData *)iofs->io_Args[0],
  670.               iofs->io_Args[1],iofs->io_Args[2]);
  671.         break;
  672.  
  673.     case FSA_EXAMINE_ALL:
  674.         error=examine_all((struct filehandle *)iofs->IOFS.io_Unit,
  675.               (struct ExAllData *)iofs->io_Args[0],
  676.               iofs->io_Args[1],iofs->io_Args[2]);
  677.         break;
  678.  
  679.     default:
  680.         error=ERROR_NOT_IMPLEMENTED;
  681.         break;
  682.     }
  683.  
  684.     /* Set error code */
  685.     iofs->io_DosError=error;
  686.  
  687.     /* If the quick bit is not set send the message to the port */
  688.     if(!(iofs->IOFS.io_Flags&IOF_QUICK))
  689.     ReplyMsg(&iofs->IOFS.io_Message);
  690.  
  691.     /* Trigger a rescedule every now and then */
  692.     if(SysBase->TaskReady.lh_Head->ln_Pri==SysBase->ThisTask->tc_Node.ln_Pri&&
  693.        SysBase->TDNestCnt<0&&SysBase->IDNestCnt<0)
  694.     {
  695.     SysBase->ThisTask->tc_State=TS_READY;
  696.     Enqueue(&SysBase->TaskReady,&SysBase->ThisTask->tc_Node);
  697.     Switch();
  698.     }
  699.  
  700.     __AROS_FUNC_EXIT
  701. }
  702.  
  703. __AROS_LH1(LONG, abortio,
  704.  __AROS_LHA(struct IOFileSys *, iofs, A1),
  705.        struct emulbase *, emulbase, 6, emul_handler)
  706. {
  707.     __AROS_FUNC_INIT
  708.     /* Everything already done. */
  709.     return 0;
  710.     __AROS_FUNC_EXIT
  711. }
  712.  
  713. static const char end=0;
  714.